package com.jl.juc.atomic.aba;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABADemo1OfAtomicStampedReference {

    /**
     * 利用AtomicStampedReference 的版本号实现 解决ABA问题
     * @param args
     */
    public static void main(String[] args) {

        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference(100, 1);
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "获得的版本号是" + stamp);

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            atomicStampedReference.compareAndSet(100, 101, stamp, stamp+1);
            System.out.println(Thread.currentThread().getName() + "第一次设置为101之后，获得的版本号是" + atomicStampedReference.getStamp());

            atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName() + "第二次设置为100之后，获得的版本号是" + atomicStampedReference.getStamp());

        },"A").start();

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "获得的版本号是" + stamp);

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            boolean b = atomicStampedReference.compareAndSet(100, 2024, stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName() + "第一次设置为2024之后，结果:"+b+"，获得的版本号是" + atomicStampedReference.getStamp());

        },"B").start();


    }

    /**
     * 测试ABA
     */
    private static void abaHappen() {
        AtomicInteger atomicInteger = new AtomicInteger(100);
        new Thread(()->{
            atomicInteger.compareAndSet(100, 101);
            System.out.println(Thread.currentThread().getName() +"=" +atomicInteger.get());
            atomicInteger.compareAndSet(101, 100);
            System.out.println(Thread.currentThread().getName() +"=" +atomicInteger.get());
        },"A").start();


        new Thread(()->{
            try {
                //保证线程A先执行
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = atomicInteger.compareAndSet(100, 2024);
            System.out.println(Thread.currentThread().getName() +"=" +atomicInteger.get());
        },"B").start();
    }

}
